package com.itheima.easy.service.impl;

import cn.hutool.core.date.LocalDateTimeUtil;
import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import com.google.common.collect.Lists;
import com.itheima.easy.base.PageResponse;
import com.itheima.easy.constant.SuperConstant;
import com.itheima.easy.entity.Dept;
import com.itheima.easy.exception.BaseException;
import com.itheima.easy.mapper.DeptMapper;
import com.itheima.easy.mapper.PostMapper;
import com.itheima.easy.service.DeptService;
import com.itheima.easy.utils.BeanConv;
import com.itheima.easy.utils.EmptyUtil;
import com.itheima.easy.utils.NoProcessing;
import com.itheima.easy.vo.DeptVo;
import com.itheima.easy.vo.TreeItemVo;
import com.itheima.easy.vo.TreeVo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Comparator;
import java.util.List;
import java.util.stream.Collectors;

/**
 * @Description：部门表服务实现类
 */
@Service
public class DeptServiceImpl implements DeptService {

    @Autowired
    DeptMapper deptMapper;

    @Resource
    private PostMapper postMapper;

    @Override
    public PageResponse<DeptVo> findDeptPage(DeptVo deptVo, int pageNum, int pageSize) {
        PageHelper.startPage(pageNum, pageSize);
        if (!EmptyUtil.isNullOrEmpty(deptVo.getParentDeptNo())){
            deptVo.setParentDeptNo(NoProcessing.processString(deptVo.getParentDeptNo()));
        }
        Page<List<Dept>> page = deptMapper.selectPage(deptVo);

        PageResponse<DeptVo> of = PageResponse.of(page, DeptVo.class);
        of.getRecords().forEach(v -> v.setCreateDay(LocalDateTimeUtil.format(v.getCreateTime(), "yyyy-MM-dd")));
        return of;
    }

    @Override
    public DeptVo createDept(DeptVo deptVo) {
        //转换DeptVo为Dept
        Dept dept = BeanConv.toBean(deptVo, Dept.class);
        String deptNo = createDeptNo(dept.getParentDeptNo());

        dept.setDeptNo(deptNo);
        int flag = deptMapper.insert(dept);
        if (flag!=1){
            throw new RuntimeException("保存部门信息出错");
        }
        return BeanConv.toBean(dept,DeptVo.class);
    }

    @Override
    public Boolean updateDept(DeptVo deptVo) {
        //转换DeptVo为Dept
        Dept dept = BeanConv.toBean(deptVo, Dept.class);
        if (dept.getDataState().equals("1")) {
            if (hasChildByDeptId(dept.getDeptNo())) {
                throw new RuntimeException("存在下级部门,不允许禁用");
            }
            if (checkDeptExistUser(dept.getDeptNo())) {
                throw new RuntimeException("部门存在用户,不允许禁用");
            }
        }
        int flag = deptMapper.updateByPrimaryKey(dept);
        if (flag==0){
            throw new RuntimeException("修改部门信息出错");
        }
        return true;
    }

    @Override
    public List<DeptVo> findDeptList(DeptVo deptVo) {
        List<Dept> deptList = deptMapper.selectList(deptVo);
        List<DeptVo> deptVos = BeanConv.toBeanList(deptList, DeptVo.class);
        deptVos.forEach(v -> v.setCreateDay(LocalDateTimeUtil.format(v.getCreateTime(), "yyyy-MM-dd")));
        return deptVos;
    }

    @Override
    public TreeVo deptTreeVo(String parentDeptNo, String[] checkedDeptNos, Integer level) {
        //根节点查询树形结构
        if (EmptyUtil.isNullOrEmpty(parentDeptNo)){
            parentDeptNo = SuperConstant.ROOT_DEPT_PARENT_ID;
        }
        List<Dept> deptList = Lists.newLinkedList();
        //指定节点查询树形结构
        DeptVo dept = DeptVo.builder()
            .dataState(SuperConstant.DATA_STATE_0)
            .parentDeptNo(NoProcessing.processString(parentDeptNo))
            .build();
        deptList.addAll(deptMapper.selectList(dept));
        if (EmptyUtil.isNullOrEmpty(deptList)){
            throw new RuntimeException("部门信息为定义！");
        }
        List<TreeItemVo> treeItemVoList  = new ArrayList<>();
        List<String> expandedIds = new ArrayList<>();
        //递归构建树形结构
        List<String> checkedDeptNoList = Lists.newArrayList();
        if (!EmptyUtil.isNullOrEmpty(checkedDeptNos)){
            checkedDeptNoList = Arrays.asList(checkedDeptNos);
        }
        //找根节点
        Dept rootDept =  deptList.stream()
            .filter(d -> SuperConstant.ROOT_DEPT_PARENT_ID.equals(d.getParentDeptNo()))
            .collect(Collectors.toList()).get(0);
        recursionTreeItem(treeItemVoList,rootDept,deptList,checkedDeptNoList,expandedIds, level);
        return TreeVo.builder()
            .items(treeItemVoList)
            .checkedIds(checkedDeptNoList)
            .expandedIds(expandedIds)
            .build();
    }

    private void recursionTreeItem(List<TreeItemVo> treeItemVoList, Dept DeptRoot, List<Dept> deptList,
                                   List<String> checkedDeptNos, List<String> expandedIds, Integer level) {
            TreeItemVo treeItem = TreeItemVo.builder()
                .id(DeptRoot.getDeptNo())
                .label(DeptRoot.getDeptName())
                .build();
            //判断是否选择
            if (!EmptyUtil.isNullOrEmpty(checkedDeptNos)&&checkedDeptNos.contains(DeptRoot.getDeptNo())){
                treeItem.setIsChecked(true);
            }else {
                treeItem.setIsChecked(false);
            }
            //是否默认展开:如果当前的部门为第二层或者第三层则展开
            if(NoProcessing.processString(DeptRoot.getDeptNo()).length()/3==3){
                expandedIds.add(DeptRoot.getDeptNo());
            }

            if(NoProcessing.processString(DeptRoot.getDeptNo()).length()/3== level + 2){
                return;
            }
            //获得当前部门下子部门
            List<Dept> childrenDept = deptList.stream()
                .filter(n -> n.getParentDeptNo().equals(DeptRoot.getDeptNo()))
                .collect(Collectors.toList());
            if (!EmptyUtil.isNullOrEmpty(childrenDept)){
                List<TreeItemVo> listChildren  = Lists.newArrayList();

                childrenDept.forEach(n->{
                    this.recursionTreeItem(listChildren,n,deptList,checkedDeptNos,expandedIds, level);});
                    treeItem.setChildren(listChildren);
            }
        treeItemVoList.add(treeItem);
    }

    @Override
    public List<DeptVo> findDeptInDeptNos(List<String> deptNos) {
        List<Dept> depts = deptMapper.findDeptInDeptNos(deptNos);
        return BeanConv.toBeanList(depts,DeptVo.class);
    }

    @Override
    public List<DeptVo> findDeptVoListByUserId(Long userId) {
        return BeanConv.toBeanList(deptMapper.findDeptListByUserId(userId),DeptVo.class);
    }

    @Override
    public String createDeptNo(String parentDeptNo) {
        if (NoProcessing.processString(parentDeptNo).length()/3==5) {
            throw new BaseException("部门最多4级");
        }
        DeptVo deptVo = DeptVo.builder().parentDeptNo(parentDeptNo).build();
        List<Dept> deptList = deptMapper.selectList(deptVo);
        //无下属节点则创建下属节点
        if (EmptyUtil.isNullOrEmpty(deptList)){
            return NoProcessing.createNo(parentDeptNo,false);
        //有下属节点则累加下属节点
        }else {
            Long deptNo = deptList.stream()
                .map(dept -> { return Long.valueOf(dept.getDeptNo());})
                .max(Comparator.comparing(i -> i)).get();
            return NoProcessing.createNo(String.valueOf(deptNo),true);
        }
    }

    @Override
    public List<DeptVo> findDeptVoListInRoleId(List<Long> roleIdSet) {
        return deptMapper.findDeptVoListInRoleId(roleIdSet);
    }

    @Transactional
    @Override
    public int deleteDeptById(String deptId) {
        if (hasChildByDeptId(deptId)) {
            throw new RuntimeException("存在下级部门,不允许删除");
        }
        if (checkDeptExistUser(deptId)) {
            throw new RuntimeException("部门存在用户,不允许删除");
        }

        postMapper.deletePostByDepId(deptId);
        return deptMapper.deleteDeptById(deptId);
    }

    /**
     * 是否存在子节点
     *
     * @param deptId 部门ID
     * @return 结果
     */
    public boolean hasChildByDeptId(String deptId) {
        int result = deptMapper.hasChildByDeptId(deptId);
        return result > 0 ? true : false;
    }

    /**
     * 查询部门是否存在用户
     *
     * @param deptId 部门ID
     * @return 结果 true 存在 false 不存在
     */
    public boolean checkDeptExistUser(String deptId) {
        int result = deptMapper.checkDeptExistUser(deptId);
        return result > 0 ? true : false;
    }
}
